/*
 * JHeuristics - The Java Meta-Heuritics Library
 * Copyright (C) 2004-2005, Universidade Federal de Campina Grande. All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package ga.tsp;

import java.io.FileNotFoundException;
import java.net.MalformedURLException;
import java.net.URL;

import org.jheuristics.Individual;
import org.jheuristics.ga.DefaultGAConfig;
import org.jheuristics.ga.DoubleFitness;
import org.jheuristics.ga.Evolver;
import org.jheuristics.ga.GAConfig;
import org.jheuristics.ga.GAStatus;
import org.jheuristics.ga.Population;
import org.jheuristics.ga.SimpleBulkFitnessEvaluator;
import org.jheuristics.ga.SimpleEvolver;
import org.jheuristics.ga.operators.CompositeOperator;
import org.jheuristics.ga.operators.ReproductionOperator;
import org.jheuristics.ga.operators.SelectionOperator;
import org.jheuristics.ga.operators.StatusPopulationChooser;
import org.jheuristics.ga.operators.probabilities.ConstantProbability;
import org.jheuristics.ga.operators.rates.ConstantRate;
import org.jheuristics.ga.operators.selectors.AllIndividualsSelector;
import org.jheuristics.ga.operators.selectors.BestIndividualsSelector;
import org.jheuristics.ga.operators.selectors.RandomSelector;
import org.jheuristics.ga.operators.selectors.StochasticUniversalSampingSelector;
import org.jheuristics.ga.scalers.ScalersFactory;
import org.jheuristics.util.Condition;
import org.jheuristics.util.DefaultRandomGenerator;
import org.jheuristics.util.conditions.AndCondition;
import org.jheuristics.util.conditions.MaxGenerationCondition;

import utils.Graph;
import utils.io.FileUtils;
import utils.io.InvalidFileException;
import utils.io.TSPLibReader;


public class TSPGAApp {

	public static void main(String[] args) throws FileNotFoundException, InvalidFileException, MalformedURLException {
		
			int maxGeneration = Integer.parseInt(args[0]);
			double mutationProbability = Double.parseDouble(args[1]);
			double xoverProbability = Double.parseDouble(args[2]);
			
			String filePath = args[3];
			int population = Integer.parseInt(args[4]);
			
			
			URL url = FileUtils.locate(filePath , TSPGAApp.class);

			Graph graph = (Graph) new TSPLibReader().read(url.getFile());
			System.out.println("graph: "+graph);
			System.out.println("++");
			RouteEvaluator routeEvaluator = new GraphRouteEvaluator(graph);
			
			CompositeOperator operator = new CompositeOperator();
			operator.addOperator(
					new SelectionOperator(
							new ConstantRate(25),
							new StochasticUniversalSampingSelector(ScalersFactory.noScaler()),
							StatusPopulationChooser.CURRENT, false, 
							StatusPopulationChooser.AVALIABLE, false));
			
			operator.addOperator(
					new ReproductionOperator(
							new ConstantRate(49), 
							new RandomSelector(), 
							new GreedyXOver(
									new ConstantProbability(xoverProbability), 
									routeEvaluator),
							StatusPopulationChooser.AVALIABLE, false, 
							StatusPopulationChooser.SELECTED, false));
			
			operator.addOperator(
					new ReproductionOperator(
							new ConstantRate(0), 
							new AllIndividualsSelector(), 
							new SwapMutation(
									new ConstantProbability(mutationProbability)),
							StatusPopulationChooser.SELECTED, false, 
							StatusPopulationChooser.SELECTED, true));
			
			operator.addOperator(
					new SelectionOperator(
							new ConstantRate(1), 
							new BestIndividualsSelector(), 
							StatusPopulationChooser.CURRENT, false, 
							StatusPopulationChooser.SELECTED, false));
			
			GAConfig config = new DefaultGAConfig(
									new TSPIndividualsFactory(routeEvaluator), operator, 
									new SimpleBulkFitnessEvaluator(
											new TSPFitnessEvaluator(routeEvaluator)), 
									new DefaultRandomGenerator());
			
			Evolver evolver = new SimpleEvolver(config, population);
			evolver.evolve(
					new MaxGenerationCondition(maxGeneration) 
					);
			
			GAStatus status = evolver.getEvolutionStatus();
			Population currentPopulation = status.getCurrentPopulation();
			Individual individual = currentPopulation.getIndividual(0);
			int age = status.getEvolutionAge();
			System.out.println("age: "+age+" "+((long)-((DoubleFitness) individual.getFitness()).toDouble()) + " " + individual.getGens());
	}

}
